package com.wisdom.smartbook.activity;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ImageFormat;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.YuvImage;
import android.os.CountDownTimer;
import android.os.Handler;
import android.os.SystemClock;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.appcompat.widget.AppCompatTextView;
import androidx.camera.core.AspectRatio;
import androidx.camera.core.Camera;
import androidx.camera.core.CameraSelector;
import androidx.camera.core.ImageAnalysis;
import androidx.camera.core.ImageProxy;
import androidx.camera.core.Preview;
import androidx.camera.lifecycle.ProcessCameraProvider;
import androidx.camera.view.PreviewView;
import androidx.core.content.ContextCompat;

import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.mlkit.vision.common.InputImage;
import com.google.mlkit.vision.face.Face;
import com.google.mlkit.vision.face.FaceDetection;
import com.google.mlkit.vision.face.FaceDetector;
import com.google.mlkit.vision.face.FaceDetectorOptions;
import com.wisdom.smartbook.R;
import com.wisdom.smartbook.base.BaseActivity;
import com.wisdom.smartbook.listener.FaceDetectionListener;
import com.wisdom.smartbook.utils.DeviceUtil;
import com.wisdom.smartbook.utils.KLog;

import org.jetbrains.annotations.NotNull;

import java.io.ByteArrayOutputStream;
import java.nio.ByteBuffer;
import java.util.List;
import java.util.concurrent.ExecutionException;

public class CameraActivity extends BaseActivity {
    private ProcessCameraProvider cameraProvider = null;
    private Preview previewUseCase = null;
    private PreviewView previewView;
    private CameraSelector cameraSelector = null;
    private int lensFacing = CameraSelector.LENS_FACING_FRONT;
    private Camera camera = null;
    private ImageAnalysis analysisUseCase = null;
    private FaceDetector detector;
    private ImageView preview_imageview;
    private TextView mCountDownTv;
    private CusCountDownTimer mCusCountDownTimer;
    protected View mCameraLayout;
    protected View shadow_view;
    private FaceDetectionListener mFaceDetectionListener;
//    @Override
//    protected void onCreate(@Nullable @org.jetbrains.annotations.Nullable Bundle savedInstanceState) {
//        super.onCreate(savedInstanceState);
//
////        Window window = getWindow();
////        if (window != null) {
////            WindowManager.LayoutParams layoutParams = window.getAttributes();
////            layoutParams.width = (int) (DeviceUtil.deviceWidth()*0.7); // 设置宽度为500dp
////            layoutParams.height = (int) (DeviceUtil.deviceWidth()*0.55); // 设置高度为300dp
////            window.setAttributes(layoutParams);
////        }
//
//    }

//    @Override
//    protected int getLayoutId() {
//        return R.layout.activity_camera;
//    }

    @Override
    protected int getLayoutId() {
        return R.layout.activity_main_new;
    }

    @Override
    protected void initView() {
        mCameraLayout = findViewById(R.id.camera_layout);
        shadow_view = findViewById(R.id.shadow_view);
        mCountDownTv = findViewById(R.id.tv_countDown);
        preview_imageview = findViewById(R.id.preview_imageview);
        previewView = findViewById(R.id.preview_view);

    }

    public void setFaceDetectionListener(FaceDetectionListener faceDetectionListener) {
        mFaceDetectionListener = faceDetectionListener;
    }

    @Override
    protected void initData() {
        FaceDetectorOptions highAccuracyOpts =
                new FaceDetectorOptions.Builder()
                        .setPerformanceMode(FaceDetectorOptions.PERFORMANCE_MODE_FAST)
                        .build();
        //2、获取人脸检测器
        detector = FaceDetection.getClient(highAccuracyOpts);
    }

    /**
     * 开始识别
     */
    protected void startFaceDetection() {

        /*
        通过 ProcessCameraProvider 获取 cameraProvider
        cameraProvider 就是我们持有的相机实例
        */
        ListenableFuture<ProcessCameraProvider> cameraProviderFuture = ProcessCameraProvider.getInstance(mActivity);
        cameraProviderFuture.addListener(new Runnable() {
            @Override
            public void run() {
                try {
                    cameraProvider = cameraProviderFuture.get();
                } catch (ExecutionException e) {
                    e.printStackTrace();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                startCamera();
            }
        }, ContextCompat.getMainExecutor(mActivity));

        mCusCountDownTimer = new CusCountDownTimer(61000, 1000);
        mCusCountDownTimer.start();
    }


    /**
     * 为人脸绘制边框
     *
     * @param bitmap
     * @param faces  采集的人脸
     * @return {@link Bitmap}
     */
    private Bitmap drawWithRectangle(Bitmap bitmap, List<Face> faces) {

        //复制一个新的Bitmap
        Bitmap copiedBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), bitmap.getConfig());

//        for (Face face : faces) {
        //获取边界状态
        // 初始化Paint
        Paint paint = new Paint();
        // 设置矩形颜色
        paint.setColor(Color.GREEN);
        // 设置绘制样式为轮廓绘制
        paint.setStyle(Paint.Style.STROKE);
        // 设置为你需要的宽度
        paint.setStrokeWidth(10);

        Canvas canvas = new Canvas(copiedBitmap);
        canvas.drawRect(faces.get(0).getBoundingBox(), paint);
//        }
        return copiedBitmap;
    }

    /**
     * 启动相机
     */
    private void startCamera() {
        if (cameraProvider != null) {
            cameraProvider.unbindAll();
            cameraSelector = new CameraSelector.Builder().requireLensFacing(lensFacing).build();
            /*
            这一步是绑定预览界面，如果不需要预览界面，这一步克注释掉
            CameraX优势体验之一：预览界面可以根据开发者需求去取舍，而Camera1和Camera2则必须要预览界面
            */
            bindPreviewUseCase();
            // 这一步是绑定相机预览数据，可以获得相机每一帧的数据
            bindAnalysisUseCase();
        }
    }

    /**
     * 绑定预览界面。不需要预览界面可以不调用
     */
    private void bindPreviewUseCase() {
        if (previewUseCase != null) {
            cameraProvider.unbind(previewUseCase);
        }

        Preview.Builder builder = new Preview.Builder();
        builder.setTargetAspectRatio(AspectRatio.RATIO_16_9).build();
        previewUseCase = builder.build();
        previewUseCase.setSurfaceProvider(previewView.getSurfaceProvider());
        cameraProvider.bindToLifecycle(this, cameraSelector, previewUseCase);
        FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) previewView.getLayoutParams();
        layoutParams.width = (int) (DeviceUtil.deviceWidth() * 0.3);
        layoutParams.height = (int) (DeviceUtil.deviceWidth() * 0.4);
        previewView.setLayoutParams(layoutParams);
    }

    private long lastTime = 0L;
    private long lastShowTime = 0L;


    private void bindAnalysisUseCase() {
        if (analysisUseCase != null) {
            cameraProvider.unbind(analysisUseCase);
        }
        ImageAnalysis.Builder builder = new ImageAnalysis.Builder().setTargetAspectRatio(AspectRatio.RATIO_16_9);
        analysisUseCase = builder.build();
        analysisUseCase.setAnalyzer(ContextCompat.getMainExecutor(this), new ImageAnalysis.Analyzer() {
            @Override
            public void analyze(@NonNull @NotNull ImageProxy imageProxy) {
                long currentTime = SystemClock.elapsedRealtime();
                long d = currentTime - lastShowTime;
                if ((currentTime - lastTime) >= 100) {
                    lastTime = currentTime;
                    processMKLImage(imageProxy);
                }
                lastShowTime = currentTime;
                //必须close,相机才会下发下一帧数据,否则会一直阻塞相机下发数据
                imageProxy.close();
            }
        });
        camera = cameraProvider.bindToLifecycle(this, cameraSelector, analysisUseCase);
    }


    Bitmap ImagetoBitmap(ImageProxy imageProxy) {
        ByteBuffer yBuffer = imageProxy.getPlanes()[0].getBuffer();// Y
        ByteBuffer vuBuffer = imageProxy.getPlanes()[2].getBuffer(); // VU
        int ySize = yBuffer.remaining();
        int vuSize = vuBuffer.remaining();
        byte[] nv21 = new byte[ySize + vuSize];
        yBuffer.get(nv21, 0, ySize);
        vuBuffer.get(nv21, ySize, vuSize);
        YuvImage yuvImage = new YuvImage(nv21, ImageFormat.NV21, imageProxy.getWidth(), imageProxy.getHeight(), null);
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        yuvImage.compressToJpeg(new Rect(0, 0, yuvImage.getWidth(), yuvImage.getHeight()), 40, out);
        byte[] imageBytes = out.toByteArray();
        return BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length);
    }


    public void processMKLImage(ImageProxy imageProxy) {
        Bitmap bitmap = null;
        try {
            bitmap = ImagetoBitmap(imageProxy);
        } catch (Exception e) {
            e.printStackTrace();
            return;
        }
        if (bitmap == null) {
            return;
        }
        KLog.d("图片尺寸" + bitmap.getWidth() + "*" + bitmap.getHeight());
        InputImage image = InputImage.fromBitmap(bitmap, imageProxy.getImageInfo().getRotationDegrees());
        Bitmap finalBitmap = bitmap;
        detector.process(image)
                .addOnSuccessListener(new OnSuccessListener<List<Face>>() {
                    @Override
                    public void onSuccess(List<Face> faces) {
                        if (faces.size() > 0) {
//                            tvFps.setText("识别到人脸");
                            KLog.d("识别到人脸");
                            preview_imageview.setImageBitmap(drawWithRectangle(finalBitmap, faces));
                            if (mFaceDetectionListener != null) {
                                mFaceDetectionListener.onFaceDetection(finalBitmap);
                            }
                        } else {
//                            tvFps.setText("请将人脸放入取景框内");
                            KLog.d("请将人脸放入取景框内");
                            preview_imageview.setImageBitmap(null);
                        }
                    }
                })
                .addOnFailureListener(new OnFailureListener() {
                    @Override
                    public void onFailure(@NonNull Exception e) {
                        KLog.e("processMKLImage", "processMKLImage onFailure: " + 1);
                    }
                });
    }


    private class CusCountDownTimer extends CountDownTimer {


        public CusCountDownTimer(long millisInFuture, long countDownInterval) {
            super(millisInFuture, countDownInterval);
        }

        @Override
        public void onTick(long millisUntilFinished) {
            int second = (int) (millisUntilFinished / 1000);
            mCountDownTv.setText(second + "秒");
        }

        @Override
        public void onFinish() {
            release();
        }

    }


    public void onClickClose(View view) {
        release();
    }

    protected void release() {
        shadow_view.setVisibility(View.GONE);
        mCameraLayout.setVisibility(View.GONE);
        preview_imageview.setImageBitmap(null);
        if (cameraProvider != null) {
            cameraProvider.unbindAll();
        }
        if (analysisUseCase != null) {
            cameraProvider.unbind(analysisUseCase);
        }
        mCusCountDownTimer.cancel();
        previewView.removeAllViews();
        camera.getCameraControl().cancelFocusAndMetering();
        camera = null;
    }
}

